#!/bin/bash
# build.sh -- a shell version of build.c for the new bootsect.s & setup.s
# author: falcon <wuzhangjin@gmail.com>
# update: 2008-10-10

bootsect=$1
setup=$2
system=$3
IMAGE=$4


# Set the biggest sys_size
# Changes from 0x20000 to 0x30000 by tigercn to avoid oversized code.
SYS_SIZE=$((0x3000 * 16))


echo 'Root device is 0x301, Swap device is 0x304, it is determined by the parameters in bootsect.s'
# Write bootsect (512 bytes, one sector) to stdout
[ ! -f "$bootsect" ] && echo "there is no bootsect binary file there" && exit -1

# if=$bootsect: if 指输入文件(input file)，指定了源文件名，这里是从$bootsect复制。
# bs=512: bs指块大小(block size)，这里设置每个块的大小为512字节。
# count=1: count指计数，即要复制的块数量。这里设置为1，也就是1个块(512bytes)
# of=$IMAGE: of意思输出文件(output file)，即数据被写入的目标文件名。这里目标文件名被设置为 $IMAGE。
# 2>&1 >/dev/null: 这部分用于重定向标准错误(2)和标准输出(1)到/dev/null，可以把所有输出屏蔽掉。它使得在执行dd命令的过程中不会有任何信息输出到控制台上。
# 简单来说，该命令从bootsect文件读取512字节，并将其写入IMAGE文件。
dd if=$bootsect bs=512 count=1 of=$IMAGE 2>&1 >/dev/null

# Write setup(4 * 512bytes, four sectors) to stdout
[ ! -f "$setup" ] && echo "there is no setup binary file there" && exit -1
# seek=1 ,指跳过1个块，也就是从512字节之后，开始复制
dd if=$setup seek=1 bs=512 count=4 of=$IMAGE 2>&1 >/dev/null

# Write system(< SYS_SIZE) to stdout
[ ! -f "$system" ] && echo "there is no system binary file there" && exit -1
system_size=$(wc -c $system | cut -d" " -f1)
[ $system_size -gt $SYS_SIZE ] && echo "the system binary is too big" && exit -1
# 2888表示一个标准1.44M软盘的总扇区数（每扇区512字节）
dd if=$system seek=5 bs=512 count=$((2888 - 1 - 4)) of=$IMAGE 2>&1 >/dev/null

# Set "device" for the root image file
# ibs=1: ibs 是输入块大小(input block size)。这里设置为1字节。
# obs=1: obs 是输出块大小(output block size)。这里也设置为1字节。
#   在 dd 命令中，ibs(input block size) 和 obs(output block size) 参数允许你精细地控制从源文件读取数据以及写入目标文件的方式。
#   当 ibs 设定为 1 时，dd 将会以一个字节一组的方式从源文件中读取数据。同样，当 obs 设定为 1 时，它将会以一个字节一组的方式向目标文件写入数据。
# count=2: count 参数表示复制多少块。由于 ibs 和 obs 都是1，所以这里就是复制2字节。
# seek=508: 此参数指示命令在开始写之前跳过 $IMAGE 文件中的前508个字节。换句话说，就是从第509字节的位置开始写入数据。(请注意，在计算机领域通常都采用0-based indexing，即从0开始数)
# of=$IMAGE: 该参数指定dd命令将数据写入哪个文件中，这里就是 $IMAGE 文件名。
# conv=notrunc: 这告诉 dd 命令即使已经往里面写了新数据也不要截断（truncate）输出文件，即不会破坏原有内容。
# 最后那部分 (2>&1 >/dev/null) 仍然是重定向所有输出到 /dev/null, 屏蔽掉任何可能出现的输出信息。
# 在dd命令中，ibs(input block size)和obs(output block size)用来分别定义读取数据和写入数据的块大小。虽然这里只是写入两个字节，但仍需要定义这两个参数。
# 当你设置的ibs=1时，表示从输入源（这里是通过echo命令生成的字节串）读取数据时，每次只读取一个字节。而设置的obs=1则告诉 dd 在向目标文件（这里是 $IMAGE）写入时以每次一个字节的方式进行。如果不设置或者设置成其他值，有可能会导致结果不符合预期。
# 举例来说，设想一种情况，在没有设定 obs, 而目标文件本身已经存在并含有数据的情况下. 如果 dd 命令按默认或更大的块尺寸操作, 即使我们只提供了两个字节，它也可能会把所在块剩余部分填充为0或其他值, 这样就会破坏原有内容。
# 因此，即便这里只是写入两个字节，我们也同时设定了 ibs=1 和 obs=1, 以保证精确地控制操作过程，并防止出现意外错误。
#echo -ne "\x$DEFAULT_MINOR_ROOT\x$DEFAULT_MAJOR_ROOT" | dd ibs=1 obs=1 count=2 seek=508 of=$IMAGE conv=notrunc 2>&1 >/dev/null
#echo -ne "\x$DEFAULT_MINOR_SWAP\x$DEFAULT_MAJOR_SWAP" | dd ibs=1 obs=1 count=2 seek=506 of=$IMAGE conv=notrunc  2>&1 >/dev/null



